package cn.itcast.nems.studentrecord.service.impl;

import cn.itcast.nems.common.constant.DiscountTypeEnum;
import cn.itcast.nems.discount.dto.DiscountSummaryDTO;
import cn.itcast.nems.studentrecord.dao.entity.StudentRecord;
import cn.itcast.nems.studentrecord.dao.entity.StudentRecordDiscount;
import cn.itcast.nems.studentrecord.dto.change.StudentRecordChangeDiscountDTO;
import cn.itcast.nems.studentrecord.dto.change.StudentRecordCreateDTO;
import cn.itcast.nems.studentrecord.enumeration.StudentRecordStateEnum;
import cn.itcast.nems.studentrecord.service.DiscountCalculator;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author liyong
 * create: 2023-11-15 09:08:40
 **/
class StudentRecordCreator {

    private final StudentRecordCreateDTO createStudentRecord;
    private final Map<Integer, DiscountSummaryDTO> discounts;
    private final DiscountCalculator discountCalculator;

    StudentRecordCreator(StudentRecordCreateDTO createStudentRecord,
                         final Map<Integer, DiscountSummaryDTO> discounts) {
        this.createStudentRecord = createStudentRecord;
        this.discounts = discounts;
        this.discountCalculator = new DiscountCalculator(new ArrayList<>(this.discounts.values()));
    }

    /**
     * 生成学籍更新对象
     *
     * @param oldStudentRecord 老学籍
     * @return 更新学籍对象
     */
    StudentRecord updateStudentRecord(StudentRecord oldStudentRecord) {
        StudentRecord update = new StudentRecord();
        this.popPropties(oldStudentRecord, false);
        this.popPropties(update, false);
        update.setId(oldStudentRecord.getId());
        return update;
    }

    StudentRecord createStudentRecord() {
        StudentRecord studentRecord = new StudentRecord();
        this.popPropties(studentRecord, true);
        return studentRecord;
    }

    private void popPropties(StudentRecord studentRecord, boolean isCreate) {
        if (isCreate) {
            studentRecord.setClazzId(createStudentRecord.getClazzId());
            studentRecord.setState(StudentRecordStateEnum.PENDING.toString());
        }
        studentRecord.setSource(createStudentRecord.getSource().toString());
        studentRecord.setClazzName(createStudentRecord.getClazzName());
        // 班级原价格
        studentRecord.setPrice(createStudentRecord.getPrice());
        // 优惠金额总额
        Integer discountAmount = createStudentRecord.getDiscountAmount();
        // 应付金额
        Integer amountDue = createStudentRecord.getAmountDue();
        if (discountAmount == null) {
            discountAmount = this.discountCalculator.calculate(this.createStudentRecord.getPrice(), amountDue);
        }
        studentRecord.setDiscountAmount(discountAmount);
        if (amountDue == null) {
            amountDue = createStudentRecord.getPrice() - discountAmount;
        }
        studentRecord.setAmountDue(amountDue);
        // 调整金额
        Integer adjustmentAmount = createStudentRecord.getAdjustmentAmount();
        adjustmentAmount = adjustmentAmount == null ? 0 : adjustmentAmount;
        studentRecord.setAdjustmentAmount(adjustmentAmount);
        // 实际应付金额
        Integer actualAmountDue = createStudentRecord.getActualAmountDue();
        if (actualAmountDue == null) {
            actualAmountDue = amountDue - adjustmentAmount;
        }
        studentRecord.setActualAmountDue(actualAmountDue);
        // 转班转入金额
        Integer transferAmount = createStudentRecord.getTransferFromAmount();
        transferAmount = transferAmount == null ? 0 : transferAmount;
        studentRecord.setTransferFromAmount(transferAmount);
        // 已付金额
        studentRecord.setPaidAmount(createStudentRecord.getPaidAmount());
        Integer refundAmount = createStudentRecord.getRefundAmount();
        refundAmount = refundAmount == null ? 0 : refundAmount;
        studentRecord.setRefundAmount(refundAmount);
        studentRecord.setInDate(createStudentRecord.getInDate());
        studentRecord.setRemark(createStudentRecord.getRemark());
        studentRecord.setLockFlag(false);
        studentRecord.setRenewalFlag(false);
        studentRecord.setAssociatedRecordId(createStudentRecord.getAssociatedRecordId());
        final StudentRecordStateEnum state = createStudentRecord.getState();
        studentRecord.setState(state != null ? state.name() : StudentRecordStateEnum.PENDING.name());
        Integer joinClassId = createStudentRecord.getJoinClassId();
        joinClassId = joinClassId == null ? 0 : joinClassId;
        studentRecord.setOldEmsRecordId(joinClassId);
    }

    List<StudentRecordDiscount> createStudentRecordDiscounts(StudentRecord studentRecord) {
        final List<StudentRecordChangeDiscountDTO> discounts = this.createStudentRecord.getDiscounts();
        List<StudentRecordDiscount> result = Collections.emptyList();
        if (discounts != null && !discounts.isEmpty()) {
            result = discounts
                    .stream()
                    .map(dto -> this.toStudentRecordDiscount(studentRecord, dto))
                    .collect(Collectors.toList());
        }
        return result;
    }

    private StudentRecordDiscount toStudentRecordDiscount(StudentRecord studentRecord, StudentRecordChangeDiscountDTO dto) {
        StudentRecordDiscount result = new StudentRecordDiscount();
        int discountId = Integer.parseInt(dto.getDiscountId());
        final DiscountSummaryDTO discountSummary = this.discounts.get(discountId);
        result.setStudentRecordId(studentRecord.getId());
        result.setDiscountId(dto.getDiscountId());
        result.setDiscountName(discountSummary.getName());
        String type = discountSummary.getType() == 0 ? DiscountTypeEnum.CASH.toString() : DiscountTypeEnum.DISCOUNT.toString();
        result.setDiscountType(type);
        // int discountAmount = this.discountCalculator.calculateOne(this.createStudentRecord.getPrice(), discountId, studentRecord.getAmountDue());
        int discountAmount = dto.getDiscountAmount();
        result.setDiscountAmount(discountAmount);
        result.setSort(dto.getSort());
        result.setDescription(discountSummary.getDescription());
        return result;
    }
}
